package com.hb.gateway.config;

import cn.hutool.core.util.ArrayUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.support.DefaultServerCodecConfigurer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Objects;

/**
 * 网关相关配置
 */
@Configuration
public class GateWayConfig {

    private static final String ALL = "*";

    @Value("${max-age:30000}")
    private String maxAge;

    @Value("${dev-model:true}")
    private boolean devModel;

    /**
     * 允许跨域host
     */
    private final String[] ACCESS_CONTROL_ALLOW_ORIGINS = {
            "https://www.baidu.com"
    };

    /**
     * 允许携带的header参数
     */
    private final String[] ACCESS_CONTROL_ALLOW_HEADERS = {
            "Origin",
            "No-Cache",
            "X-Requested-With",
            "If-Modified-Since",
            "Pragma",
            "Last-Modified",
            "Cache-Control",
            "Expires",
            "Content-Type",
            "X-E4M-With",
            "X-Access-Token"
    };

    @Bean
    public ServerCodecConfigurer serverCodecConfigurer(){
        return new DefaultServerCodecConfigurer();
    }

    @Bean
    public WebFilter corsFilter() {
        return (ServerWebExchange ctx, WebFilterChain chain) -> {
            ServerHttpRequest request = ctx.getRequest();
            if (!CorsUtils.isCorsRequest(request)) {
                return chain.filter(ctx);
            }
            HttpHeaders requestHeaders = request.getHeaders();
            ServerHttpResponse response = ctx.getResponse();
            HttpHeaders headers = response.getHeaders();
            preHandle(headers, requestHeaders, devModel);

            if (request.getMethod() == HttpMethod.OPTIONS) {
                response.setStatusCode(HttpStatus.OK);
                return Mono.empty();
            }
            return chain.filter(ctx);
        };
    }

    /**
     * 设置跨域访问
     *
     * @param headers
     * @param requestHeaders
     * @param isDev          是否为开发环境
     */
    private void preHandle(HttpHeaders headers, HttpHeaders requestHeaders, boolean isDev) {
        String origin = requestHeaders.getOrigin();
        HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
        if (isDev) {
            headers.set(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
        } else {
            if (ArrayUtil.contains(ACCESS_CONTROL_ALLOW_ORIGINS, origin)) {
                headers.set(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
            }
        }
        List<String> accessControlRequestHeaders = requestHeaders.getAccessControlRequestHeaders();
        accessControlRequestHeaders.remove("accept");
        accessControlRequestHeaders.remove("crossdomain");
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,
                ArrayUtil.join(ACCESS_CONTROL_ALLOW_HEADERS, ","));
        if (requestMethod != null) {
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());
        }
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
        headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);
        headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, maxAge);
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, maxAge);
    }


}
